package org.nstack.header.host;

import org.nstack.header.cluster.ClusterInventory;
import org.nstack.header.query.ExpandedQueries;
import org.nstack.header.query.ExpandedQuery;
import org.nstack.header.query.Queryable;
import org.nstack.header.search.Inventory;
import org.nstack.header.search.TypeField;
import org.nstack.header.zone.ZoneInventory;
import org.nstack.header.allocator.HostCapacityInventory;
import org.nstack.header.configuration.PythonClassInventory;
import org.nstack.header.vm.VmInstanceInventory;

import javax.persistence.JoinColumn;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;



@Inventory(mappingVOClass = HostVO.class)
@PythonClassInventory
@ExpandedQueries({
        @ExpandedQuery(expandedField = "zone", inventoryClass = ZoneInventory.class,
                foreignKey = "zoneUuid", expandedInventoryKey = "uuid"),
        @ExpandedQuery(expandedField = "cluster", inventoryClass = ClusterInventory.class,
                foreignKey = "clusterUuid", expandedInventoryKey = "uuid"),
        @ExpandedQuery(expandedField = "vmInstance", inventoryClass = VmInstanceInventory.class,
                foreignKey = "uuid", expandedInventoryKey = "hostUuid")
})
public class HostInventory implements Serializable {

    private String zoneUuid;

    private String name;

    private String uuid;

    private String clusterUuid;

    private String description;

    private String managementIp;

    @TypeField
    private String hypervisorType;

    private String state;

    private String status;

    @Queryable(mappingClass = HostCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "totalCpu"))
    private Long totalCpuCapacity;

    @Queryable(mappingClass = HostCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "availableCpu"))
    private Long availableCpuCapacity;

    @Queryable(mappingClass = HostCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "cpuSockets"))
    private Integer cpuSockets;

    @Queryable(mappingClass = HostCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "totalMemory"))
    private Long totalMemoryCapacity;

    @Queryable(mappingClass = HostCapacityInventory.class,
            joinColumn = @JoinColumn(name = "uuid", referencedColumnName = "availableMemory"))
    private Long availableMemoryCapacity;


    private Timestamp createDate;

    private Timestamp lastOpDate;

    protected HostInventory(HostVO vo) {
        this.setStatus(vo.getStatus().toString());
        this.setCreateDate(vo.getCreateDate());
        this.setDescription(vo.getDescription());
        this.setHypervisorType(vo.getHypervisorType());
        this.setLastOpDate(vo.getLastOpDate());
        this.setManagementIp(vo.getManagementIp());
        this.setName(vo.getName());
        this.setState(vo.getState().toString());
        this.setUuid(vo.getUuid());
        this.setZoneUuid(vo.getZoneUuid());
        this.setClusterUuid(vo.getClusterUuid());
        if (vo.getCapacity() != null) {
            this.setTotalCpuCapacity(vo.getCapacity().getTotalCpu());
            this.setAvailableCpuCapacity(vo.getCapacity().getAvailableCpu());
            this.setTotalMemoryCapacity(vo.getCapacity().getTotalMemory());
            this.setAvailableMemoryCapacity(vo.getCapacity().getAvailableMemory());
            this.setCpuSockets(vo.getCapacity().getCpuSockets());
        }
    }

    public HostInventory() {
    }

    public static HostInventory valueOf(HostVO vo) {
        return new HostInventory(vo);
    }

    public static List<HostInventory> valueOf(Collection<HostVO> vos) {
        List<HostInventory> invs = new ArrayList<HostInventory>(vos.size());
        for (HostVO vo : vos) {
            invs.add(HostInventory.valueOf(vo));
        }
        return invs;
    }

    public Long getTotalCpuCapacity() {
        return totalCpuCapacity;
    }

    public void setTotalCpuCapacity(Long totalCpuCapacity) {
        this.totalCpuCapacity = totalCpuCapacity;
    }

    public Long getAvailableCpuCapacity() {
        return availableCpuCapacity;
    }

    public Integer getCpuSockets() {
        return cpuSockets;
    }

    public void setCpuSockets(Integer cpuSockets) {
        this.cpuSockets = cpuSockets;
    }

    public void setAvailableCpuCapacity(Long availableCpuCapacity) {
        this.availableCpuCapacity = availableCpuCapacity;
    }

    public Long getTotalMemoryCapacity() {
        return totalMemoryCapacity;
    }

    public void setTotalMemoryCapacity(Long totalMemoryCapacity) {
        this.totalMemoryCapacity = totalMemoryCapacity;
    }

    public Long getAvailableMemoryCapacity() {
        return availableMemoryCapacity;
    }

    public void setAvailableMemoryCapacity(Long availableMemoryCapacity) {
        this.availableMemoryCapacity = availableMemoryCapacity;
    }

    public String getZoneUuid() {
        return zoneUuid;
    }

    public void setZoneUuid(String zoneUuid) {
        this.zoneUuid = zoneUuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getManagementIp() {
        return managementIp;
    }

    public void setManagementIp(String managementIp) {
        this.managementIp = managementIp;
    }

    public String getHypervisorType() {
        return hypervisorType;
    }

    public void setHypervisorType(String hypervisorType) {
        this.hypervisorType = hypervisorType;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Timestamp getCreateDate() {
        return createDate;
    }

    public void setCreateDate(Timestamp createDate) {
        this.createDate = createDate;
    }

    public Timestamp getLastOpDate() {
        return lastOpDate;
    }

    public void setLastOpDate(Timestamp lastOpDate) {
        this.lastOpDate = lastOpDate;
    }

    public String getClusterUuid() {
        return clusterUuid;
    }

    public void setClusterUuid(String clusterUuid) {
        this.clusterUuid = clusterUuid;
    }
}
